# -*- coding: utf-8 -*-

from globalvariables import *
from treelib import Tree, Node
import re


def is_valid_section_number(s):
    #    正则表达式解释：
    #    ^：匹配字符串的开始。
    #    (0|[1-9]\d*)：匹配“0”或者以1到9之间的数字开头的任意数量的数字（包括0）。[1-9] 确保编号不以0开头，除非编号就是“0”。
    #    (\.\d+)*：匹配点后面跟着一个或多个数字的组合，这个组合可以出现零次或多次。
    #    $：匹配字符串的结束。
    pattern1 = r'^(0|[1-9]\d*(\.\d+)*)$'
    pattern2 = r'^(0|[1-9]\d*(\_\d+)*)$'
    match1 = re.match(pattern1, s) or s == "root"
    match2 = re.match(pattern2, s) or s == "root"
    match = match1 or match2
    return match


class Outline(Tree):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def getSurveyContent(self, section_identifier: str = "root"):
        if not is_valid_section_number(section_identifier):
            raise ValueError(f"节编号{section_identifier}不符合格式规范")
        node_id = section_identifier.replace(".", "_")
        subtree = self.subtree(node_id)
        outline_string = subtree.show(line_type="ascii", stdout=False)  # 获取树结构字符串，使用show方法的访问顺序
        lines = outline_string.split("\n")[:-1]  # 获取每行字符串，每行对应一个节点，对应一个章节
        for idx, line in enumerate(lines):
            # 仅保留每行字符串中的节编号
            lines[idx] = line.split(" ")[-1]
        for idx, line in enumerate(lines):
            # 将节编号的展示格式转换为章节索引格式
            lines[idx] = line.replace(".", "_")
        survey_content = f""
        for line in lines:
            # 获取对应节编号的章节内容
            survey_content += f"{'#' * (line.count('_') + 2)} {line.replace('_', '.')} {self.get_node(line).data['title']}\n{self.get_node(line).data['content']}\n\n"
        return survey_content

    def showSurveyOutline(self, section_identifier: str = "root", format: int = 0):
        if not is_valid_section_number(section_identifier):
            raise ValueError(f"节编号{section_identifier}不符合格式规范")
        # 将节编号的展示格式转换为章节索引格式
        node_id = section_identifier.replace(".", "_")
        subtree = self.subtree(node_id)
        outline_string = subtree.show(line_type="ascii", stdout=False)  # 获取树结构字符串，使用show方法的访问顺序
        lines = outline_string.split("\n")[:-1]  # 获取每行字符串，每行对应一个节点，对应一个章节
        line_pres = []  # 存储行前缀，保留树的展示结构信息
        line_mids = []
        line_posts = []  # 存储节编号
        for line in lines:
            # 将每行字符串中的带有结构信息前缀和节编号存在两个数组中
            line_pre, line_mid, line_post = line.rpartition(" ")
            line_pres.append(line_pre)
            line_mids.append(line_mid)
            line_posts.append(line_post)
        section_keys = []
        for idx in range(len(line_posts)):
            # 将节编号的展示格式转换为章节索引格式
            section_keys.append(line_posts[idx].replace(".", "_"))
        survey_outline = f"{self.get_node(self.root).data['title']}\n\n"
        for idx in range(len(line_posts)):
            # 获取对应节编号的章节内容
            tmp_info = ""
            if format == 0:
                tmp_info = self.get_node(section_keys[idx]).data['title']
            if format == 1:
                tmp_info = self.get_node(section_keys[idx]).data['title'] + \
                           "：" + self.get_node(section_keys[idx]).data['description']
            survey_outline += f"{line_pres[idx]}{line_mids[idx]}{line_posts[idx]} {tmp_info}\n"
        return survey_outline

    def getSubTreeLeaves(self, section_identifier: str = "root"):
        if not is_valid_section_number(section_identifier):
            raise ValueError(f"节编号{section_identifier}不符合格式规范")
        # 将节编号的展示格式转换为章节索引格式
        node_id = section_identifier.replace(".", "_")
        subtree = self.subtree(node_id)
        leaves = subtree.leaves()
        return leaves

    def get_children(self, section_identifier: str = "root"):
        if not is_valid_section_number(section_identifier):
            raise ValueError(f"节编号{section_identifier}不符合格式规范")
        # 将节编号的展示格式转换为章节索引格式
        node_id = section_identifier.replace(".", "_")
        children = self.children(node_id)
        return children

    def remove_sub_outline(self, section_identifier: str = "root"):
        if not is_valid_section_number(section_identifier):
            raise ValueError(f"节编号{section_identifier}不符合格式规范")
        # 将节编号的展示格式转换为章节索引格式
        node_id = section_identifier.replace(".", "_")
        self.remove_subtree(node_id)

    def get_last_child_identifier(self, parent_identifier: str = "root"):
        # 获取指定父节点的所有子节点
        children = self.get_children(parent_identifier)

        if not children:
            return None  # 如果没有子节点，返回 None

        # 获取最后一个子节点的 section_identifier
        last_child = children[-1]  # 获取最后一个子节点
        last_identifier = last_child.tag  # 最后一个子节点的 identifier
        # 将 section_identifier 分割成数字部分
        parts = last_identifier.split('.')

        # 将最后一部分转化为整数，并加 1
        last_part = int(parts[-1]) + 1

        # 重建新的 section_identifier
        parts[-1] = str(last_part)

        # 将新的 section_identifier 重新组合起来
        new_identifier = '.'.join(parts)
        return new_identifier


class Section(Node):
    def __init__(self, section_identifier: str, *args, **kwargs):
        """
        :param section_identifier: 章节id，以节编号的展示格式输入，如2.3.1
        :param args: 任意数量的位置参数
        :param kwargs: 任意数量的关键字参数
        """
        # 从 kwargs 中提取 title, description, content，并提供默认值
        title = kwargs.pop('title', "")
        description = kwargs.pop('description', "")
        content = kwargs.pop('content', "")
        reference_1 = kwargs.pop('reference_1', [])  # 处理 reference_1
        reference_2 = kwargs.pop('reference_2', [])  # 处理 reference_2
        used_ref = kwargs.pop('used_ref', {})
        listed_ref = kwargs.pop('listed_ref', [])

        section_data = {
            "title": title,
            "description": description,
            "reference_1": reference_1,  # 确保 reference 进入 section_data
            "reference_2": reference_2,
            "used_ref": used_ref,
            "listed_ref": listed_ref,
            "content": content
        }

        if not is_valid_section_number(section_identifier):
            raise ValueError(f"节编号{section_identifier}不符合格式规范")

        # 将节编号的展示格式转换为章节索引格式
        node_id = section_identifier.replace(".", "_")

        # 调用父类的构造函数，传递任意额外的参数
        super().__init__(tag=section_identifier, identifier=node_id, data=section_data, *args, **kwargs)


if __name__ == "__main__":
    t = Outline()
    r = Section(section_identifier="root", title="A survey on deep 3D human pose estimation", description="",
                content="")
    s1 = Section(section_identifier="1", title="Introduction", content="")
    s2 = Section(section_identifier="1.1", title="Previous survey", content="")
    s3 = Section(section_identifier="1.2", title="Scope of the study", content="")
    s4 = Section(section_identifier="2", title="3D-HPE problem-solving strategies", content="")
    s5 = Section(section_identifier="2.1", title="Problem-solving stage", content="")
    s6 = Section(section_identifier="2.1.1", title="Single-stage or End-to-end", content="")
    s7 = Section(section_identifier="2.1.2", title="2D-to-3D lifting", content="")
    s8 = Section(section_identifier="2.2", title="Joint keypoint coordinates", content="")
    s9 = Section(section_identifier="2.2.1", title="Person-centric", content="")
    s10 = Section(section_identifier="2.2.2", title="Camera-centric", content="")
    s11 = Section(section_identifier="2.3", title="Multi-person paradigms", content="")
    s12 = Section(section_identifier="2.3.1", title="Top-down paradigm", content="")
    s13 = Section(section_identifier="2.3.2", title="Bottom-up paradigm", content="")
    s14 = Section(section_identifier="2.3.3", title="Hybrid/single-stage", content="")
    s15 = Section(section_identifier="2.4", title="Deterministic approach vs. probabilistic vs. diffusion-based",
                  content="")
    s16 = Section(section_identifier="2.4.1", title="Deterministic approach", content="")
    s17 = Section(section_identifier="2.4.2", title="Probabilistic approach", content="")
    s18 = Section(section_identifier="2.4.3", title="Diffusion-based approach", content="")
    s19 = Section(section_identifier="2.5", title="Problem solving space", content="")
    s20 = Section(section_identifier="2.5.1", title="Pixel-based approach", content="")
    s21 = Section(section_identifier="2.5.2", title="Voxel-based approach", content="")
    s22 = Section(section_identifier="2.5.3", title="NeRF-based approach", content="")
    s23 = Section(section_identifier="2.6", title="Emerging techniques and needs", content="")
    s24 = Section(section_identifier="3", title="Single-person 3D-HPE methods", content="")
    s25 = Section(section_identifier="3.1", title="3D-HPE from monocular image", content="")
    s26 = Section(section_identifier="3.1.1", title="CNN-based methods", content="")
    s27 = Section(section_identifier="3.1.2", title="GCN-based methods", content="")
    s28 = Section(section_identifier="3.1.3", title="transformer-based methods", content="")
    s29 = Section(section_identifier="3.1.4", title="Hybrid/other methods", content="")
    s30 = Section(section_identifier="3.2", title="3D-HPE from monocular video", content="")
    s31 = Section(section_identifier="3.2.1", title="CNN-based methods", content="")
    s32 = Section(section_identifier="3.2.2", title="GCN-based methods", content="")
    s33 = Section(section_identifier="3.2.3", title="transformer-based methods", content="")
    s34 = Section(section_identifier="3.2.4", title="Hybrid methods", content="")
    s35 = Section(section_identifier="3.3", title="3D-HPE from multi-view images", content="")
    s36 = Section(section_identifier="3.3.1", title="CNN-based methods", content="")

    t.add_node(r)
    t.add_node(s1, 'root')
    t.add_node(s2, '1')
    t.add_node(s3, '1')
    t.add_node(s4, r)
    t.add_node(s5, s4)
    t.add_node(s6, '2_1')
    t.add_node(s7, s5)
    t.add_node(s8, s4)
    t.add_node(s9, s8)
    t.add_node(s10, s8)
    t.add_node(s11, s4)
    t.add_node(s12, s11)
    t.add_node(s13, s11)
    t.add_node(s14, s11)
    t.add_node(s15, s4)
    t.add_node(s16, s15)
    t.add_node(s17, s15)
    t.add_node(s18, s15)
    t.add_node(s19, s4)
    t.add_node(s20, s19)
    t.add_node(s21, s19)
    t.add_node(s22, s19)
    t.add_node(s23, s4)
    t.add_node(s24, r)
    t.add_node(s25, s24)
    t.add_node(s26, s25)
    t.add_node(s27, s25)
    t.add_node(s28, s25)
    t.add_node(s29, s25)
    t.add_node(s30, s24)
    t.add_node(s31, s30)
    t.add_node(s32, s30)
    t.add_node(s33, s30)
    t.add_node(s34, s30)
    t.add_node(s35, s24)
    t.add_node(s36, s35)
    print(t.get_node('root'))
    subtree = t.subtree("2")
    # 遍历所有内容为空的子章节
    for blank_node in subtree.all_nodes_itr():
        if blank_node.data['content'].strip() == "":
            print()
    # def post_order_traversal(node_id, reference_chunks_c, outline):
    #     """
    #     自底向上遍历树节点并修改节点值
    #     :param node: 当前节点
    #     :param modify_func: 修改节点值的函数
    #     """
    #     if outline.get_node(node_id) == None:
    #         return
    #
    #     # 递归遍历所有子节点
    #     for child in outline.get_children(node_id):
    #         post_order_traversal(child.identifier, reference_chunks_c, outline)
    #     node = outline.get_node(node_id)
    #     node.data['title'] = 'abc'
    # post_order_traversal('root', [], t)
    # # print(t.show(line_type="ascii", stdout=False))
    # print(t.showSurveyOutline(format=0))
    # print(t.get_children('3_1_1'))
    # print(t.get_node('3_1_1'))
    # sections = t.children('root')
    # for section in sections:
    #     section_leaves = t.getSubTreeLeaves(section.identifier)
    #     for section_leaf in section_leaves:
    #         print(section_leaf)
    #     print('\n\n')
